/*
 * Copyright 2007-2008  Lukasz Laszko lukaszlaszko@gmail.com
 * 
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for any purpose and without fee is hereby
 * granted, provided that the above copyright notice appear in all
 * copies and that both that the copyright notice and this
 * permission notice and warranty disclaimer appear in supporting
 * documentation, and that the name of the author not be used in
 * advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 * 
 * The author disclaim all warranties with regard to this
 * software, including all implied warranties of merchantability
 * and fitness.  In no event shall the author be liable for any
 * special, indirect or consequential damages or any damages
 * whatsoever resulting from loss of use, data or profits, whether
 * in an action of contract, negligence or other tortious action,
 * arising out of or in connection with the use or performance of
 * this software. 
 */
package org.pg.biomedics.asr.mbeans;

import java.lang.management.ManagementFactory;
import java.util.Map;
import java.util.HashMap;
import java.util.UUID;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

/**
 * Builds appropriate MBean object
 * @author Lukasz Laszko
 */
public class MBeanBuilder 
{
    // <editor-fold desc="Constants">
    
    public static final String VOICE_ENGINE_MBEAN = "VoiceEngine";
    public static final String TASK_SCHEDULER_MBEAN = "TaskScheduler";
    
    // </editor-fold>
    
    // <editor-fold desc="Fields">
    
    private static MBeanBuilder instance;      
    
    private Map mBeanNames = new HashMap();
    
    // </editor-fold>
    
    // <editor-fold desc="Constructors">
    
    /**
     * Private constrctor prevents class instantiation
     */
    private MBeanBuilder() {}
    
    // </editor-fold>
    
    // <editor-fold desc="Statis methods">
    
    /**
     * Static factory method for signelton MBeanBuilder class instance
     * with support for lazy init
     * @return MBeanBuilder singelton instance
     */
    public static MBeanBuilder getInstance()
    {
        if (instance == null)
            instance = new MBeanBuilder();
        
        return instance;
    }
    
    // </editor-fold>
        
    // <editor-fold desc="Methods">
    
    /**
     * Creates new MBean according to given type name
     * @param typeCode MBean type name
     * @return registered instance of MBean
     */
    public Object createMBean(String typeCode) throws MBeanException
    {
        // input params validation
        if (typeCode == null)
            throw new MBeanException("Can't create MBean, MBean type code can't be null");
        
        try
        {
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            ObjectName mBeanName = new ObjectName(String.format("org.pg.biomedics.asr.mbeans:type=%s, name=%s", typeCode, 
                                                                                                                UUID.randomUUID().toString()));            
            if (typeCode.equals(VOICE_ENGINE_MBEAN))
            {
                Object mBean = new VoiceEngineInfo();
                server.registerMBean(mBean, mBeanName);
                this.mBeanNames.put(mBean, mBeanName);
                
                return mBean;
            }
            else if (typeCode.equals(TASK_SCHEDULER_MBEAN))
            {
                Object mBean = new TaskSchedulerInfo();
                server.registerMBean(mBean, mBeanName);
                this.mBeanNames.put(mBean, mBeanName);
                
                return mBean;
            }
            else
            {
                 throw new MBeanException("Unknown type code");
            }
        }
        catch (Exception ex)
        {
            throw new MBeanException(String.format("Can't create MBean for type code %s", typeCode), ex);
        }
    }
        
    /**
     * Removes MBean from JMX server
     * @param mBean MBean instance which should be removed from server
     * @throws org.pg.biomedics.asr.mbeans.MBeanException
     */
    public void destroyMBean(Object mBean) throws MBeanException
    {
        if (!this.mBeanNames.containsKey(mBean))
            return;
        
        try
        {
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            server.unregisterMBean((ObjectName)this.mBeanNames.get(mBean));
        }
        catch (Exception ex)
        {
            throw new MBeanException("Can't destroy MBean", ex);
        }
    }
    
    // </editor-fold>
}
